<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:xh="http://www.w3.org/1999/xhtml"
 xmlns:xf="http://www.w3.org/2002/xforms"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:ev="http://www.w3.org/2001/xml-events"
 xmlns:js="http://www.formsplayer.com/inlineScript"
>
	<head>
		<title>Hub</title>

		<link rel="bindings" href="hub-bindings.xml" />

		<script type="text/javascript" src="gadgets/common/scripts/events.js">/**/</script>

		<script type="text/javascript" src="gadgets/common/scripts/resize.js">/**/</script>

		<script type="text/javascript" src="gadgets/common/scripts/move.js">/**/</script>

		<script type="text/javascript" src="gadgets/common/scripts/dragdrop.js">/**/</script>

		<script type="text/javascript" src="gadgets/common/scripts/timers.js">/**/</script>

		<script type="text/javascript" src="gadgets/common/scripts/geometry.js">/**/</script>

		<script type="text/javascript" src="hub.js">/**/</script>

		<link rel="stylesheet" href="hubbub.css" type="text/css" media="screen" />

		<link rel="stylesheet" href="hub.css" type="text/css" media="screen" />

		<xf:model id="mdl-gadgets">
			<xf:instance id="inst-gadget">
				<gadget xmlns="">
					<type />

					<value />
				</gadget>
			</xf:instance>

			<xf:instance id="inst-persistence">
				<persistence xmlns="">
					<resource />
				</persistence>
			</xf:instance>

			<xf:bind nodeset="instance('inst-persistence')/resource" calculate="concat('cookie:hubbub-0.5/hub-', instance('inst-gadget')/value, '.xhtml')" />

			<xf:instance id="inst-hub" src="hub-default.xhtml" />

			<xf:submission id="sbm-hub-load" method="get" replace="instance" instance="inst-hub" validate="false" serialize="false">
				<xf:resource value="instance('inst-persistence')/resource" />
			</xf:submission>

			<xf:submission id="sbm-hub-save" method="put" replace="none" ref="instance('inst-hub')" validate="false" relevant="false">
				<xf:resource value="instance('inst-persistence')/resource" />
			</xf:submission>

			<xf:bind nodeset="instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]/*[@property = 'time']/*[@property = 'clock']/*[@property = 'h']" calculate="number(instance('inst-time')/h) + number(../../*[@property = 'offset']/*[@property = 'h'])" />

			<xf:bind nodeset="instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]/*[@property = 'time']/*[@property = 'clock']/*[@property = 'm']" calculate="number(instance('inst-time')/m) + number(../../*[@property = 'offset']/*[@property = 'm'])" />

			<xf:bind nodeset="instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]/*[@property = 'time']/*[@property = 'clock']/*[@property = 'formatted']" calculate="concat(format-number(number(../*[@property = 'h']) + floor(number(../*[@property = 'm']) div 60) + 24 mod 24, '00'), ':', format-number(number(../*[@property = 'm']) + 60 mod 60, '00'), ':', format-number(number(instance('inst-time')/s), '00'))" />

			<xf:instance id="inst-authorisation">
				<authorisation />
			</xf:instance>

			<xf:instance id="inst-friendfeed-user">
				<friendfeed-user xmlns="" />
			</xf:instance>

			<xf:submission id="sbm-friendfeed-user" method="get" replace="instance" instance="inst-friendfeed-user" serialize="false">
				<xf:resource value="concat('http://friendfeed.com/api/user/', (instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'friendfeed'], '/profile?format=xml')" />

				<xf:header>
					<xf:name value="'Authorization'" />
					<xf:value value="instance('inst-authorisation')" />
				</xf:header>
			</xf:submission>

			<xf:instance id="inst-friendfeed-list">
				<friendfeed-list xmlns="" />
			</xf:instance>

			<xf:submission id="sbm-friendfeed-list" method="get" replace="instance" instance="inst-friendfeed-list" serialize="false">
				<xf:resource value="concat('http://friendfeed.com/api/list/', instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/@name, '/profile?format=xml')" />

				<xf:header>
					<xf:name value="'Authorization'" />
					<xf:value value="instance('inst-authorisation')" />
				</xf:header>
			</xf:submission>

			<xf:instance id="inst-friendfeed-brightkite">
				<friendfeed-brightkite xmlns="" />
			</xf:instance>

			<xf:submission id="sbm-friendfeed-brightkite" method="get" replace="instance" instance="inst-friendfeed-brightkite" serialize="false" mode="synchronous">
				<xf:resource value="concat('http://friendfeed.com/api/feed/user?nickname=', (instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'friendfeed'], '&amp;service=brightkite&amp;format=xml')" />

				<xf:header>
					<xf:name value="'Authorization'" />
					<xf:value value="instance('inst-authorisation')" />
				</xf:header>
			</xf:submission>

			<xf:instance id="inst-geonames-timezone">
				<geonames-timezone xmlns="" />
			</xf:instance>

			<xf:submission id="sbm-geonames-timezone" method="get" replace="instance" instance="inst-geonames-timezone" serialize="false" mode="synchronous">
				<xf:resource value="concat('http://ws.geonames.org/timezone?lat=', substring-before((instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'location'], ';'), '&amp;lng=', substring-after((instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'location'], ';'))" />
			</xf:submission>

			<xf:instance id="inst-iterators">
				<iterators xmlns="">
					<friendfeed-users />
					<friendfeed-lists />
					<friendfeed-listusers />
					<friendfeed-listsfirstuser>1</friendfeed-listsfirstuser>
					<bubs />
				</iterators>
			</xf:instance>

			<xf:bind nodeset="instance('inst-iterators')">
				<xf:bind id="iterator-friendfeed-users" nodeset="friendfeed-users" />

				<xf:bind id="iterator-friendfeed-lists" nodeset="friendfeed-lists" />

				<xf:bind id="iterator-friendfeed-listusers" nodeset="friendfeed-listusers" />

				<xf:bind id="iterator-friendfeed-listsfirstuser" nodeset="friendfeed-listsfirstuser" />

				<xf:bind id="iterator-bubs" nodeset="bubs" />
			</xf:bind>

			<xf:instance id="inst-templates" src="templates.xml" />

			<xf:instance id="inst-drop">
				<drop xmlns="">
					<id />
					<src />
					<alt />
				</drop>
			</xf:instance>

			<xf:instance id="inst-time">
				<time xmlns="">
					<now>1970-01-01T00:00:00</now>
					<h>0</h>
					<m>0</m>
					<s>0</s>
				</time>
			</xf:instance>

			<xf:bind nodeset="instance('inst-time')">
				<xf:bind nodeset="h" calculate="substring(../now, 12, 2)" />

				<xf:bind nodeset="m" calculate="substring(../now, 15, 2)" />

				<xf:bind nodeset="s" calculate="substring(../now, 18, 2)" />
			</xf:bind>

			<xf:instance id="inst-size">
				<size xmlns="" />
			</xf:instance>

			<xf:instance id="inst-geometry">
				<geometry xmlns="">
					<x />
					<y />
				</geometry>
			</xf:instance>

			<xf:instance id="inst-view">
				<view xmlns="" />
			</xf:instance>

			<xf:instance id="inst-gadget-update">
				<gadget-update xmlns="">
					<index />
					<property />
					<value />
				</gadget-update>
			</xf:instance>

			<xf:instance id="inst-delete-bubs">
				<delete-bubs xmlns="" />
			</xf:instance>

			<xf:instance id="inst-delete-bubs-done">
				<delete-bubs-done xmlns="">false</delete-bubs-done>
			</xf:instance>

			<xf:instance id="inst-close">
				<close xmlns="" />
			</xf:instance>

			<xf:instance id="inst-close-done">
				<close-done xmlns="">false</close-done>
			</xf:instance>

			<xf:instance id="inst-googlemaps">
				<googlemaps xmlns="">
					<apikey directory="http://hubbub.googlecode.com/svn/trunk/src/">ABQIAAAAtiayLvivBA_sjLrjcC0kKBRhIXe-oRVPD5umdPsX9wukwaYTzxRuPCM4yGz4era_REp5vA6DN6ifWQ</apikey>
				</googlemaps>
			</xf:instance>

			<xf:instance id="inst-show">
				<show xmlns="">true</show>
			</xf:instance>

			<xf:instance id="inst-scripts">
				<scripts xmlns="">
					<retval />
				</scripts>
			</xf:instance>

			<xf:bind id="script-retval" nodeset="instance('inst-scripts')/retval" />

			<xf:action ev:event="xforms-ready">
				<xf:setvalue ref="instance('inst-time')/now" value="now()" />

				<xf:setvalue bind="script-retval" value="js:TIMERS_setTimer(1000, 'repeat', 'mdl-gadgets', 'backplane-clock-tick', 'hubbub-hub-clock')" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_initUpdateHandler()" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_initDropHandler()" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_initNotifyHandlers()" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_initViewHandler()" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_initGadgetUpdateHandler()" />

				<xf:setvalue bind="script-retval" value="js:HUB_initHandlers()" />

				<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-request-authorisation', 'friendfeed')" />
			</xf:action>

			<xf:action ev:event="xforms-model-destruct">
				<xf:setvalue bind="script-retval" value="js:TIMERS_destroyTimer('hubbub-hub-clock')" />
			</xf:action>

			<xf:action ev:event="backplane-clock-tick">
				<xf:setvalue ref="instance('inst-time')/now" value="now()" />
			</xf:action>

			<xf:action ev:event="backplane-notify-authorisation">
				<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-ready')" />
			</xf:action>

			<xf:action ev:event="backplane-update">
				<xf:send submission="sbm-hub-load" />
			</xf:action>

			<xf:action ev:observer="sbm-hub-load" ev:event="xforms-submit-error">
				<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-show')" />
			</xf:action>

			<xf:action ev:observer="sbm-hub-load" ev:event="xforms-submit-done">
				<xf:setvalue if="instance('inst-hub')/xh:head/xh:meta[@property = 'size']/@content != ''" bind="script-retval" value="js:EVENTS_send('backplane-set-size', string(instance('inst-hub')/xh:head/xh:meta[@property = 'size']/@content))" />

				<!--
					HACK: Adding this delay appears to work round some flakiness in Ubiquity formsPlayer.
				-->
				<xf:setvalue bind="script-retval" value="js:TIMERS_setTimer(300, 'single', 'mdl-gadgets', 'hack-friendfeed-load', 'hack-friendfeed-load')" />
			</xf:action>

			<xf:action ev:event="hack-friendfeed-load">
				<xf:setvalue bind="script-retval" value="js:TIMERS_destroyTimer('hack-friendfeed-load')" />

				<xf:setvalue bind="iterator-friendfeed-lists" value="1" />

				<xf:send submission="sbm-friendfeed-list" />
			</xf:action>

			<xf:action ev:observer="sbm-hub-save" ev:event="xforms-submit-error">
				<xf:dispatch name="hubbub-hub-show" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:observer="sbm-hub-save" ev:event="xforms-submit-done">
				<xf:dispatch name="hubbub-hub-show" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:event="hubbub-hub-show">
				<xf:action if="instance('inst-show') = 'true'">
					<xf:setvalue ref="instance('inst-show')" value="'false'" />

					<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-show')" />
				</xf:action>
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-user" ev:event="xforms-submit">
				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'blog']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'brightkite']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'delicious']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'digg']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'greader']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'last.fm']" />

				<xf:delete nodeset="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'twitter']" />
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-user" ev:event="xforms-submit-done">
				<xf:action if="instance('inst-friendfeed-user')/service[id = 'blog']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'blog']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'blog']"
					 value="instance('inst-friendfeed-user')/service[id = 'blog']/username"
					/>
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'brightkite']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'brightkite']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'brightkite']"
					 value="instance('inst-friendfeed-user')/service[id = 'brightkite']/username"
					/>

					<!--
						TODO: The brightkite submission is apparently quite unreliable, so we need to come up
						      with an architecture that allows us to invoke it asynchronously. Currently, it
						      uses the friendfeed-users iterator to resolve the submission resource during
						      invocation and then to store the result correctly during xforms-submit-done
						      handling. The submission result does contain the details of the friendfeed user
						      that it is for, so removing the dependency from the xforms-submit-done handler
						      should be straightforward. Addressing the submission resource resolution is more
						      complicated. I think we need to queue up the iterator values in a space-separated
						      list. I shall look into doing this in my local copy now, but in the meantime I am
						      disabling this submission.
					-->
					<!--xf:send submission="sbm-friendfeed-brightkite" /-->
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'delicious']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'delicious']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'delicious']"
					 value="instance('inst-friendfeed-user')/service[id = 'delicious']/username"
					/>
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'digg']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'digg']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'digg']"
					 value="instance('inst-friendfeed-user')/service[id = 'digg']/username"
					/>
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'googlereader']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'greader']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'greader']"
					 value="instance('inst-friendfeed-user')/service[id = 'googlereader']/username"
					/>
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'lastfm']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'last.fm']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'last.fm']"
					 value="instance('inst-friendfeed-user')/service[id = 'lastfm']/username"
					/>
				</xf:action>

				<xf:action if="instance('inst-friendfeed-user')/service[id = 'twitter']">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'services']/*[@property = 'twitter']"
					 context="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'twitter']"
					 value="instance('inst-friendfeed-user')/service[id = 'twitter']/username"
					/>
				</xf:action>

				<!--
					HACK: This delay is to work around reliability issues in Ubiquity formsPlayer.
				-->
				<xf:setvalue bind="script-retval" value="js:TIMERS_setTimer(100, 'single', 'mdl-gadgets', 'hack-friendfeed-users-iterate', 'hack-friendfeed-users-iterate')" />
			</xf:action>

			<xf:action ev:event="hack-friendfeed-users-iterate">
				<xf:setvalue bind="script-retval" value="js:TIMERS_destroyTimer('hack-friendfeed-users-iterate')" />

				<xf:setvalue bind="iterator-friendfeed-users" value="number(.) + 1" />

				<xf:dispatch name="hubbub-fetch-friendfeed-users" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-list" ev:event="xforms-submit">
				<xf:action while="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[contains(@typeof, 'hubbub:bub')]">
					<xf:delete nodeset="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[contains(@typeof, 'hubbub:bub')]" />

					<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-force-resize', '0|-58')" />
				</xf:action>
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-list" ev:event="xforms-submit-error">
				<xf:setvalue bind="iterator-friendfeed-users" value="number(../friendfeed-listsfirstuser)" />

				<xf:dispatch name="hubbub-fetch-friendfeed-users" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-list" ev:event="xforms-submit-done">
				<xf:setvalue bind="iterator-friendfeed-listusers" value="1" />

				<xf:action while="number(instance('inst-iterators')/friendfeed-listusers) &lt;= count(instance('inst-friendfeed-list')/user)">
					<xf:insert
					 origin="instance('inst-templates')/*[@id = 'bub']"
					 context="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]"
					 nodeset="*"
					 at="count(../*)"
					 position="after"
					/>

					<xf:setvalue
					 ref="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[@id = 'bub']/*[@property = 'foaf:name']"
					 value="instance('inst-friendfeed-list')/user[number(instance('inst-iterators')/friendfeed-listusers)]/name"
					/>

					<xf:setvalue
					 ref="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[@id = 'bub']/*[@rel = 'foaf:depiction']/@href"
					 value="concat('http://friendfeed.com/', instance('inst-friendfeed-list')/user[number(instance('inst-iterators')/friendfeed-listusers)]/nickname, '/picture?size=medium')"
					/>

					<xf:setvalue
					 ref="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[@id = 'bub']/*[@property = 'friendfeed']"
					 value="instance('inst-friendfeed-list')/user[number(instance('inst-iterators')/friendfeed-listusers)]/nickname"
					/>

					<xf:setvalue
					 ref="instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')][number(instance('inst-iterators')/friendfeed-lists)]/*[@id = 'bub']/@id"
					 value="concat('list-', instance('inst-iterators')/friendfeed-lists, '-bub-', instance('inst-iterators')/friendfeed-listusers)"
					/>

					<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-force-resize', '0|58')" />

					<xf:setvalue bind="iterator-friendfeed-listusers" value="number(.) + 1" />
				</xf:action>

				<!--
					HACK: This delay is to work around reliability issues in Ubiquity formsPlayer.
				-->
				<xf:setvalue bind="script-retval" value="js:TIMERS_setTimer(100, 'single', 'mdl-gadgets', 'hack-friendfeed-lists-iterate', 'hack-friendfeed-lists-iterate')" />
			</xf:action>

			<xf:action ev:event="hack-friendfeed-lists-iterate">
				<xf:setvalue bind="script-retval" value="js:TIMERS_destroyTimer('hack-friendfeed-lists-iterate')" />

				<xf:setvalue bind="iterator-friendfeed-lists" value="number(.) + 1" />

				<xf:action if="number(instance('inst-iterators')/friendfeed-lists) &gt; count(instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')])">
					<xf:setvalue bind="iterator-friendfeed-users" value="number(../friendfeed-listsfirstuser)" />

					<xf:dispatch name="hubbub-fetch-friendfeed-users" target="mdl-gadgets" />
				</xf:action>

				<xf:send if="number(instance('inst-iterators')/friendfeed-lists) &lt;= count(instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')])" submission="sbm-friendfeed-list" />
			</xf:action>

			<xf:action ev:observer="sbm-friendfeed-brightkite" ev:event="xforms-submit-done">
				<xf:action if="instance('inst-friendfeed-brightkite')/entry/geo/lat and instance('inst-friendfeed-brightkite')/entry/geo/long">
					<xf:setvalue
					 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'location']"
					 value="concat(instance('inst-friendfeed-brightkite')/entry/geo/lat[1], ';', instance('inst-friendfeed-brightkite')/entry/geo/long[1])"
					/>

					<!--
						TODO: The geonames submission is apparently quite unreliable, so we need to come up
						      with an architecture that allows us to invoke it asynchronously. Currently, it
						      uses the friendfeed-users iterator to resolve the submission resource during
						      invocation and then to store the result correctly during xforms-submit-done
						      handling. We could address the submission resource resolution by building up
						      a space-separated list of iterator values to use as a stack. However, this
						      technique would not be sane for xforms-submit-done handling because we can not
						      guarantee the order that submission results will arrive in. Actually, though,
						      I've just realised that this distinction might be moot. Given that the geonames
						      submission is invoked on completion of the brightkite one, it is only the
						      brightkite submission that we must make asynchronous. If we can achieve that,
						      then this geonames submission could be reinstated in its current form (although
						      it would need to make its own copy of the iterator value, which is simple).
					-->
					<!--xf:send submission="sbm-geonames-timezone" /-->
				</xf:action>
			</xf:action>

			<xf:action ev:observer="sbm-geonames-timezone" ev:event="xforms-submit-done">
				<xf:setvalue
				 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'time']/*[@property = 'offset']/*[@property = 'h']"
				 value="substring-before(instance('inst-geonames-timezone')/timezone/rawOffset, '.')"
				/>

				<xf:setvalue
				 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'time']/*[@property = 'offset']/*[@property = 'm']"
				 value="number(substring(substring-after(instance('inst-geonames-timezone')/timezone/rawOffset, '.'), 1, 1)) * 6"
				/>

				<xf:setvalue
				 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'time']/@timezone"
				 value="instance('inst-geonames-timezone')/timezone/timezoneId"
				/>

				<xf:setvalue
				 ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-iterators')/friendfeed-users)]/*[@property = 'time']/@country"
				 value="instance('inst-geonames-timezone')/timezone/countryName"
				/>
			</xf:action>

			<xf:action ev:event="backplane-drop-response">
				<xf:dispatch if="starts-with(instance('inst-drop')/id, 'friend-')" name="hubbub-drop-friend" target="mdl-gadgets" />

				<xf:dispatch if="starts-with(instance('inst-drop')/id, 'list-')" name="hubbub-drop-list" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:event="hubbub-drop-friend">
				<xf:insert
				 origin="instance('inst-templates')/*[@id = 'bub']"
				 context="instance('inst-hub')/xh:body"
				 nodeset="*"
				 at="count(../*)"
				 position="after"
				/>

				<xf:setvalue
				 ref="instance('inst-hub')/xh:body/*[@id = 'bub']/*[@property = 'foaf:name']"
				 value="instance('inst-drop')/alt"
				/>

				<xf:setvalue
				 ref="instance('inst-hub')/xh:body/*[@id = 'bub']/*[@rel = 'foaf:depiction']/@href"
				 value="instance('inst-drop')/src"
				/>

				<xf:setvalue
				 ref="instance('inst-hub')/xh:body/*[@id = 'bub']/*[@property = 'friendfeed']"
				 value="substring-after(instance('inst-drop')/id, 'friend-')"
				/>

				<xf:setvalue
				 ref="instance('inst-hub')/xh:body/*[@id = 'bub']/@id"
				 value="concat('bub-', count(instance('inst-hub')/xh:body/*[contains(@typeof, 'hubbub:bub')]))"
				/>

				<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-force-resize', '0|58')" />

				<xf:setvalue bind="iterator-friendfeed-users" value="count(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])" />

				<xf:dispatch name="hubbub-fetch-friendfeed-users" target="mdl-gadgets" />
			</xf:action>

			<xf:action ev:event="hubbub-drop-list">
				<xf:insert
				 origin="instance('inst-templates')/*[@id = 'list']"
				 context="instance('inst-hub')/xh:body"
				 nodeset="*"
				 at="count(../*)"
				 position="after"
				/>

				<xf:setvalue ref="instance('inst-hub')/xh:body/*[@id = 'list']/@name" value="substring-after(instance('inst-drop')/id, 'list-')" />

				<xf:setvalue ref="instance('inst-hub')/xh:body/*[@id = 'list']/@label" value="instance('inst-drop')/alt" />

				<xf:setvalue ref="instance('inst-hub')/xh:body/*[@id = 'list']/@icon" value="instance('inst-drop')/src" />

				<xf:setvalue ref="instance('inst-hub')/xh:body/*[@id = 'list']/@id" value="concat('list-', count(instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')]))" />

				<xf:setvalue bind="iterator-friendfeed-listsfirstuser" value="count(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]) + 1" />

				<xf:setvalue bind="iterator-friendfeed-lists" value="count(instance('inst-hub')/xh:body/*[contains(@typeof, 'friendfeed:list')])" />

				<xf:send submission="sbm-friendfeed-list" />
			</xf:action>

			<xf:action ev:event="backplane-notify-size">
				<xf:setvalue
				 ref="instance('inst-hub')/xh:head/xh:meta[@property = 'size']/@content"
				 value="instance('inst-size')"
				/>

				<xf:send submission="sbm-hub-save" />
			</xf:action>

			<xf:action ev:event="backplane-gadget-update">
				<xf:setvalue ref="(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])[number(instance('inst-gadget-update')/index)]/*[@property = instance('inst-gadget-update')/property]" value="instance('inst-gadget-update')/value" />

				<xf:send submission="sbm-hub-save" />
			</xf:action>

			<xf:action ev:event="hubbub-fetch-friendfeed-users">
				<xf:action if="number(instance('inst-iterators')/friendfeed-users) &gt; count(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])">
					<xf:send submission="sbm-hub-save" />

					<xf:setvalue bind="script-retval" value="js:EVENTS_send('hubbub-hub-update')" />
				</xf:action>

				<xf:send if="number(instance('inst-iterators')/friendfeed-users) &lt;= count(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')])" submission="sbm-friendfeed-user" />
			</xf:action>

			<xf:action ev:event="hubbub-hub-delete-bubs" if="instance('inst-delete-bubs') = instance('inst-gadget')/value">
				<xf:action if="instance('inst-delete-bubs-done') = 'false'">
					<xf:setvalue ref="instance('inst-delete-bubs-done')" value="'true'" />

					<xf:action while="count(instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]) &gt; 0">
						<xf:delete nodeset="instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]" />

						<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-force-resize', '0|-58')" />
					</xf:action>

					<xf:send submission="sbm-hub-save" />

					<!--
						NOTE: For now, dispatching hubbub-hub-update here is unnecessary, because the only time we
						      get to this point is when deleting a hub. However, if this code is ever invoked from
						      other scenarios, we may need to consider reinstating the hubbub-hub-update event.
					-->
					<!--xf:setvalue bind="script-retval" value="js:EVENTS_send('hubbub-hub-update')" /-->
				</xf:action>
			</xf:action>

			<xf:action ev:event="hubbub-hub-close" if="instance('inst-close') = instance('inst-gadget')/value">
				<xf:action if="instance('inst-close-done') = 'false'">
					<xf:setvalue ref="instance('inst-close-done')" value="'true'" />

					<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-close')" />
				</xf:action>
			</xf:action>
		</xf:model>
	</head>

	<body ondragenter="event.returnValue = false;" ondragover="event.returnValue = false;" ondrop="event.returnValue = false;">
		<div class="actions">
			<xf:trigger appearance="minimal">
				<xf:label class="view-button">
					<img src="gadgets/common/images/button_fg.png" alt="Change the bub view" class="button22" />
				</xf:label>

				<xf:action ev:event="DOMActivate">
					<xf:setvalue ref="instance('inst-view')" value="if(. = '' or . = 'avatar', 'location', if(. = 'location', 'time', 'avatar'))" />

					<xf:dispatch name="backplane-switch-view" target="mdl-gadgets" />
				</xf:action>
			</xf:trigger>

			<xf:trigger appearance="minimal">
				<xf:label class="twitter-button">
					<img src="gadgets/common/images/button_fg.png" alt="View the Twitter feed for this hub" class="button22" />
				</xf:label>

				<xf:setvalue ev:event="DOMActivate" bind="script-retval" value="js:EVENTS_send('backplane-open', concat('e,0', '|friendfeed.feed twitter|', instance('inst-persistence')/resource, ' all 0'))" />
			</xf:trigger>

			<xf:trigger appearance="minimal">
				<xf:label class="friendfeed-button">
					<img src="gadgets/common/images/button_fg.png" alt="View the FriendFeed feed for this hub" class="button22" />
				</xf:label>

				<xf:setvalue ev:event="DOMActivate" bind="script-retval" value="js:EVENTS_send('backplane-open', concat('e,0', '|friendfeed.feed|', instance('inst-persistence')/resource, ' all 0'))" />
			</xf:trigger>
		</div>

		<div class="bub-container">
			<div id="droptarget" ondragenter="DRAGDROP.onDragEnter(event);" ondragover="DRAGDROP.onDragOver(event);" ondrop="DRAGDROP.onDrop();"></div>
		</div>

		<xf:repeat id="rpt-bubs" nodeset="instance('inst-hub')/xh:body//*[contains(@typeof, 'hubbub:bub')]">
			<div class="bub-container">
				<xf:switch>
					<xf:case id="view-avatar">
						<xf:trigger appearance="minimal">
							<xf:label>
								<xf:output class="bub" value="concat('&lt;img src=&quot;', *[@rel = 'foaf:depiction']/@href, '&quot; alt=&quot;', *[@property = 'foaf:name'], '&quot; onerror=&quot;event.srcElement.src = &amp;quot;gadgets/friendfeed/default-user.png&amp;quot;;&quot; /&gt;')" />
							</xf:label>

							<xf:action ev:event="DOMActivate">
								<xf:setvalue ref="instance('inst-geometry')/x" value="js:GEOMETRY_getXPos()" />

								<xf:setvalue ref="instance('inst-geometry')/x" value="number(.) + 35" />

								<xf:setvalue if="number(instance('inst-geometry')/x) &lt; 0" ref="instance('inst-geometry')/x" value="0" />

								<xf:setvalue ref="instance('inst-geometry')/y" value="js:GEOMETRY_getYPos()" />

								<xf:setvalue ref="instance('inst-geometry')/y" value="number(.) + 111 + (index('rpt-bubs') - 1) * 58" />

								<xf:setvalue if="number(instance('inst-geometry')/y) &lt; 0" ref="instance('inst-geometry')/y" value="0" />

								<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-open', concat(instance('inst-geometry')/x, ',', instance('inst-geometry')/y, ',c|bub|', instance('inst-persistence')/resource, ' ', index('rpt-bubs'), ' e,', (index('rpt-bubs') - 1) * 58 + 82))" />
							</xf:action>
						</xf:trigger>
					</xf:case>

					<xf:case id="view-location">
						<xf:output class="bub" value="concat('&lt;img src=&quot;http://maps.google.com/staticmap?center=', substring-before(*[@property = 'location'], ';'), ',', substring-after(*[@property = 'location'], ';'), '&amp;zoom=0&amp;size=50x50&amp;key=', instance('inst-googlemaps')/apikey, '&quot; alt=&quot;', *[@property = 'foaf:name'], '&quot; /&gt;')" />
					</xf:case>

					<xf:case id="view-time">
						<xf:output class="bub" ref="*[@property = 'time']/*[@property = 'clock']/*[@property = 'formatted']" appearance="xaml:analogue-clock" />
					</xf:case>
				</xf:switch>

				<xf:action ev:observer="mdl-gadgets" ev:event="backplane-switch-view">
					<xf:toggle if="instance('inst-view') = 'avatar'" case="view-avatar" />

					<xf:toggle if="instance('inst-view') = 'location'" case="view-location" />

					<xf:toggle if="instance('inst-view') = 'time'" case="view-time" />
				</xf:action>

				<xf:trigger appearance="minimal">
					<xf:label class="close-button">
						<img src="gadgets/common/images/button_fg.png" alt="Delete this bub" class="button16" />
					</xf:label>

					<xf:action ev:event="DOMActivate">
						<xf:delete nodeset="." />

						<xf:send submission="sbm-hub-save" />

						<xf:setvalue bind="script-retval" value="js:EVENTS_send('backplane-force-resize', '0|-58')" />

						<xf:setvalue bind="script-retval" value="js:EVENTS_send('hubbub-hub-update')" />
					</xf:action>
				</xf:trigger>
			</div>
		</xf:repeat>
	</body>
</html>
